﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.ComponentModel;
using System.ServiceModel;
using System.Threading;
using Microsoft.WVB.Framework;
using Microsoft.WVB.Services.MicMembershipService;

namespace Microsoft.WVB.Services
{
    
    public class MICMembershipProvider : MembershipProvider<MembershipUser>, IDisposable
    {
        private MembershipServiceClient _service = null;
        private SendOrPostCallback onGetUserCompleted;
        private SendOrPostCallback onCreateUserCompleted;
        private SendOrPostCallback onDeleteUserCompleted;
        private SendOrPostCallback onUpdateUserCompleted;
        private SendOrPostCallback onChangePasswordCompleted;
        private SendOrPostCallback onValidateUserCompleted;

        public MICMembershipProvider(string path)
            : base(path) {}

        protected override void Initialize()
        {
            base.Initialize();

            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
            EndpointAddress address = new EndpointAddress(serviceRoot);
            _service = new MembershipServiceClient(binding, address);

            InitializeDelegates();
        }

        private void InitializeDelegates()
        {
            Action<object> raiseGetUserCompleted = o =>
            {
                AcquireCompletedEventArgs<MembershipUser> e = o as AcquireCompletedEventArgs<MembershipUser>;
                if (e != null)
                    OnGetUserCompleted(e);
            };
            onGetUserCompleted = new SendOrPostCallback(raiseGetUserCompleted);

            Action<object> raiseCreateUserCompleted = o =>
            {
                AcquireCompletedEventArgs<MembershipUser> e = o as AcquireCompletedEventArgs<MembershipUser>;
                if (e != null)
                    OnCreateUserCompleted(e);
            };
            onCreateUserCompleted = new SendOrPostCallback(raiseCreateUserCompleted);

            Action<object> raiseDeleteUserCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnDeleteUserCompleted(e);
            };
            onDeleteUserCompleted = new SendOrPostCallback(raiseDeleteUserCompleted);

            Action<object> raiseUpdateUserCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnUpdateUserCompleted(e);
            };
            onUpdateUserCompleted = new SendOrPostCallback(raiseUpdateUserCompleted);

            Action<object> raiseChangePasswordCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnChangePasswordCompleted(e);
            };
            onChangePasswordCompleted = new SendOrPostCallback(raiseChangePasswordCompleted);

            Action<object> raiseValidateUserCompleted = o =>
            {
                NotifyActionCompletedEventArgs e = o as NotifyActionCompletedEventArgs;
                if (e != null)
                    OnValidateUserCompleted(e);
            };
            onValidateUserCompleted = new SendOrPostCallback(raiseValidateUserCompleted);
        }

        public override void GetUserAsync(string username, object userData)
        {
            GetMembershipUserRequest req = new GetMembershipUserRequest();
            req.Username = username;

            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);
            AsyncCallback ac = null;
            

            ac = iAsyncResult =>
                {
                    AcquireCompletedEventArgs<MembershipUser> args = null;
                    GetMembershipUserResponse response = null;
                    WVBServiceException e = null;
                    MembershipUser localuser = null;

                    AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;

                    try
                    {
                        aop.SynchronizationContext.OperationStarted();
                        response = ((IMembershipService)_service).EndGetUser(iAsyncResult);
                    }
                    catch (TimeoutException timeoutException)
                    {
                        e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.GetUserAsync", timeoutException);
                    }
                    catch (FaultException fException)
                    {
                        e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.GetUserAsync", fException);
                    }
                    catch (CommunicationException comException)
                    {
                        e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "GetUserAsync"), "CommunicationException", "MICMembershipProvider.GetUserAsync", comException);
                    }
                    catch (Exception generalException)
                    {
                        e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "GetUserAsync"), "Unknown", "MICMembershipProvider.GetUserAsync", generalException);
                    }

                    if (response != null)
                        localuser = EntityConverter.ConvertToMemberhipUser(response.User);
                    else
                        e = new WVBServiceException(Strings.WCF_Services_Exception_InternalServerError, Strings.MICProfileProvider_Exception_Serialization, "MICMembershipProvider.GetUserAsync", new NullReferenceException());

                    args = new AcquireCompletedEventArgs<MembershipUser>(localuser, e, false, aop.UserSuppliedState);
                    aop.PostOperationCompleted(onGetUserCompleted, args); 
                };

            ((IMembershipService)_service).BeginGetUser(req, ac, op);
        }

        public override void GetUserAsync(object primaryKey, object userData)
        {
            throw new NotImplementedException();
        }

        public override void CreateUserAsync(string username, string password, string email, object userData)
        {
            AsyncCallback ac = null;
            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);

            CreateMembershipUserRequest req = new CreateMembershipUserRequest();
            req.Username = username;
            req.Email = email;
            req.Password = password;
            
            ac = iAsyncResult =>
                {
                    AcquireCompletedEventArgs<MembershipUser> args = null;
                    CreateMembershipUserResponse response = null;
                    AsyncOperation operation = iAsyncResult.AsyncState as AsyncOperation;
                    WVBServiceException e = null;
                    MembershipUser localuser = null;

                    try 
                    {
                        response = ((IMembershipService)_service).EndCreateUser(iAsyncResult);                 
                    }
                    catch (TimeoutException timeoutException)
                    {
                        e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.CreateUserAsync", timeoutException);
                    }
                    catch (FaultException fException)
                    {
                        e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.CreateUserAsync", fException);
                    }
                    catch (CommunicationException comException)
                    {
                        e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "CreateUserAsync"), "CommunicationException", "MICMembershipProvider.CreateUserAsync", comException);
                    }
                    catch (Exception generalException)
                    {
                        e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "CreateUserAsync"), "Unknown", "MICMembershipProvider.CreateUserAsync", generalException);
                    }

                    if ((e == null) && (response != null))
                    {
                        if (response.Status == MembershipCreateStatus.Success)
                        {
                            localuser = EntityConverter.ConvertToMemberhipUser(response.User);
                        }
                        else
                        {
                            e = new WVBServiceException(Strings.WCF_Services_Exception_InternalServerError, "", "MICMembershipProvider.CreateUserAsync", null);
                        }
                    }
                    
                    args = new AcquireCompletedEventArgs<MembershipUser>(localuser, e, false, operation.UserSuppliedState);
                    operation.PostOperationCompleted(onCreateUserCompleted, args); 
                };

            ((IMembershipService)_service).BeginCreateUser(req, ac, op);
        }

        public override void DeleteUserAsync(string username, object userData)
        {
            AsyncCallback ac = null;
            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);

            DeleteMembershipUserRequest request = new DeleteMembershipUserRequest();
            request.Username = username;
            request.DeleteAllRelatedData = true;

 
            ac = iAsyncResult => 
            {
                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;
                bool success = false;
                WVBServiceException e = null;

                try
                {
                    success = ((IMembershipService)_service).EndDeleteUser(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.DeleteUserAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.DeleteUserAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "DeleteUserAsync"), "CommunicationException", "MICMembershipProvider.DeleteUserAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "DeleteUserAsync"), "Unknown", "MICMembershipProvider.DeleteUserAsync", generalException);
                }

                NotifyActionCompletedEventArgs arg = new NotifyActionCompletedEventArgs(success, Microsoft.WVB.Framework.Action.Delete, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onDeleteUserCompleted, arg);
            };

            ((IMembershipService)_service).BeginDeleteUser(request, ac, op);
        }

        public override void UpdateUserAsync(MembershipUser user, object userData)
        {
            AsyncCallback ac = null;
            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);

            UpdateMembershipUserRequest request = new UpdateMembershipUserRequest();
            request.User = EntityConverter.ConvertToWVBUser(user);

            ac = iAsyncResult =>
            {
                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;
                bool success = false;
                WVBServiceException e = null;

                try
                {
                    ((IMembershipService)_service).EndUpdateUser(iAsyncResult);
                    success = true;
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.UpdateUserAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.UpdateUserAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "UpdateUserAsync"), "CommunicationException", "MICMembershipProvider.UpdateUserAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "UpdateUserAsync"), "Unknown", "MICMembershipProvider.UpdateUserAsync", generalException);
                }

                NotifyActionCompletedEventArgs arg = new NotifyActionCompletedEventArgs(success, Microsoft.WVB.Framework.Action.Update, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onUpdateUserCompleted, arg);
            };

            ((IMembershipService)_service).BeginUpdateUser(request, ac, op);
        }

        public override void ValidateUserAsync(string username, string password, object userData)
        {
            AsyncCallback ac = null;
            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);

            ValidateMembershipUserRequest request = new ValidateMembershipUserRequest();
            request.Username = username;
            request.Password = password;

            ac = iAsyncResult =>
            {
                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;
                bool valid = false;
                WVBServiceException e = null;

                try
                {
                    valid = ((IMembershipService)_service).EndValidateUser(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.ValidateUserAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.ValidateUserAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "ValidateUserAsync"), "CommunicationException", "MICMembershipProvider.ValidateUserAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "ValidateUserAsync"), "Unknown", "MICMembershipProvider.ValidateUserAsync", generalException);
                }

                NotifyActionCompletedEventArgs arg = new NotifyActionCompletedEventArgs(valid, Microsoft.WVB.Framework.Action.Validate, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onValidateUserCompleted, arg);
            };

            ((IMembershipService)_service).BeginValidateUser(request, ac, op);
        }

        public override void ChangePasswordAsync(string username, string oldpassword, string newpassword, object userData)
        {
            AsyncCallback ac = null;
            AsyncOperation op = AsyncOperationManager.CreateOperation(userData);

            ac = iAsyncResult =>
            {
                AsyncOperation aop = iAsyncResult.AsyncState as AsyncOperation;
                bool succeed = false;
                WVBServiceException e = null;

                try
                {
                    succeed = ((IMembershipService)_service).EndChangePassword(iAsyncResult);
                }
                catch (TimeoutException timeoutException)
                {
                    e = new WVBServiceException(timeoutException.Message, "TimeoutException", "MICMembershipProvider.ChangePasswordAsync", timeoutException);
                }
                catch (FaultException fException)
                {
                    e = new WVBServiceException(fException.Message, "FaultException", "MICMembershipProvider.ChangePasswordAsync", fException);
                }
                catch (CommunicationException comException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "ChangePasswordAsync"), "CommunicationException", "MICMembershipProvider.ChangePasswordAsync", comException);
                }
                catch (Exception generalException)
                {
                    e = new WVBServiceException(String.Format(Strings.WCF_Services_Exception_Unknown, "ChangePasswordAsync"), "Unknown", "MICMembershipProvider.ChangePasswordAsync", generalException);
                }

                NotifyActionCompletedEventArgs arg = new NotifyActionCompletedEventArgs(succeed, Microsoft.WVB.Framework.Action.ChangePassword, e, false, aop.UserSuppliedState);
                aop.PostOperationCompleted(onChangePasswordCompleted, arg);
            };

            ((IMembershipService)_service).BeginChangePassword(username, oldpassword, newpassword, ac, op);
        }

        public override void CancelAsync()
        {
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (_service != null)
            {
                _service = null;
            }
        }

        #endregion
    }
}
